<?php
namespace lib\kindEditor;

use lib\Images\ImageCut;

/**
 * Class UploadFiles
 * @package lib\kindeditor
 *  文件上传
 * 使用方法：
 *                  $file = new UploadFiles();
 *                  $result = $file->save() ; or  $file->setFileExt($ext_array)->setFileSize(1000000)->save() ;
 *                  $this->display($result , 'json');
 */

/**
 * @Auth: JH <hu@lunaz.cn>
 * Class UploadFiles
 * @package lib\kindEditor
 */
class UploadFiles
{
    /**
     * 文件主目录
     * @var
     */
    protected $file_root;

    /**
     * 文件主目录对应的url
     * @var
     */
    protected $file_host;
    /**
     * 保存路径
     * @var
     */
    protected $save_path;
    /**
     * 完整的URL
     * @var
     */
    protected $url;

    /**
     * 文件相应url
     * @var
     */
    protected $file_url;
    /**
     * 保存的文件名
     * @var string
     */
    protected $save_name;

    /**
     * 提交上传处理的文件名
     * @var string
     */
    protected $upload_file_name;

    /**
     * 提交上传处理的文件的基础信息
     * @var array
     */
    protected $upload_file_base_info = array();
    /**
     * 默认允许上传文件格式
     * @var array
     */
    protected $file_ext = array(
        'image' => array('gif', 'jpg', 'jpeg', 'png', 'bmp'),
        'thumb' => array('jpg', 'jpeg', 'png'),
        'flash' => array('swf', 'flv'),
        'media' => array('swf', 'flv', 'mp3', 'mp4', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb'),
        'file' => array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2', 'pdf'),
    );
    /**
     * 默认允许上传文件大小
     * @var int
     */
    protected $file_size = 8388608;  // 1MB = 1048576 B
    /**
     * 文件类型目录
     * @var
     */
    protected $file_type;

    protected $status_error = array(
        '上传成功',
        '超过php.ini允许的大小。',
        '超过表单允许的大小。',
        '图片只有部分被上传。',
        '请选择图片。',
        '找不到临时目录。',
        '写文件到硬盘出错。',
        '文件上传停止扩展。'
    );


    /**
     * 构造函数
     * UploadFiles constructor.
     *
     * @param $file_root
     * @param $file_host
     * @param string $file_type
     * @param string $save_name
     * @param string $upload_file_name
     */

    function __construct($file_root, $file_host, $file_type = '', $save_name = '', $upload_file_name = 'imgFile')
    {
        $this->file_root = $file_root;
        $this->file_host = $file_host;
        $this->save_name = $save_name ? $save_name : $this->randName();
        $this->upload_file_name = $upload_file_name;
        $this->file_type = $file_type ? $file_type : (isset($_GET['dir']) ? $_GET['dir'] : 'file');
        if (!array_key_exists($this->file_type, $this->file_ext)) {
            $this->error('非指定类型文件目录');
        }
    }

    /**
     * 设置文件类型
     *
     * @param array $ext 数据格式参照默认格式传入
     *
     * @return $this
     */
    function setFileExt(array $ext)
    {
        $this->file_ext = $ext;
        return $this;
    }

    /**
     * 设置允许上传大小
     *
     * @param int $size
     *
     * @return $this
     */
    function setFileSize($size)
    {
        if (is_int($size)) {
            $this->file_size = $size;
        }
        return $this;
    }

    /**
     * 保存上传文件
     * @return array
     */
    function save()
    {
        $ret = $this->moveUploadFile();
        if ($ret === false) {
            $this->error('上传文件失败');
        }
        return array(
            'error' => 0,
            'url' => $this->url,
            'file_url' => $this->file_url,
            'path' => $this->save_path
        );
    }

    function saveThumb($size = '100x100', $save_original = false)
    {
        if (!in_array($this->file_type, array('image', 'thumb'))) {
            throw new \Exception($this->file_type . ' 文件类型不支持裁剪');
        }

        $result = array('error' => 1, 'error');

        $move = $this->moveUploadFile();
        if ($move) {
            $ori_info = array(
                'ori_url' => $this->url,
                'ori_path' => $this->save_path,
                'ori_file_url' => $this->file_url
            );

            $cut = new ImageCut($this->save_path);

            list($max_w, $max_h) = explode('x', $size);

            //获取缩略图文件名
            $this->save_name = $this->randName($this->file_type);

            //编译保存路径;
            $this->buildSaveFile();

            //开始裁剪
            $cut->setCutSize($max_w, $max_h)
                ->cut(
                    array('x' => 0, 'y' => 0, 'w' => 0, 'h' => 0),
                    $this->save_path
                );

            $result = array(
                'error' => 0,
                'url' => $this->url,
                'file_url' => $this->file_url,
                'path' => $this->save_path
            );

            if ($save_original) {
                $result += $ori_info;
            } else {
                unlink($ori_info['ori_path']);
            }
        }

        return $result;
    }

    /**
     * @param $resource
     *
     * @return bool
     */
    protected function saveImage($resource)
    {
        switch ($this->upload_file_base_info['file_type']) {
            case 'jpg':
            case 'jpeg':
            case 'pjpeg':
                return imagejpeg($resource, $this->save_path, 100);
            case 'gif':
                return imagegif($resource, $this->save_path);
            case 'png':
                return imagepng($resource, $this->save_path);
            default:
                return imagegd2($resource, $this->save_path);
        }
    }


    /**
     * 移动文件到上传目录
     * @return bool
     */
    protected function moveUploadFile()
    {
        $this->buildSaveFile();
        return move_uploaded_file($this->upload_file_base_info['tmp_name'], $this->save_path);
    }

    /**
     * 生成文件保存信息
     */
    protected function buildSaveFile()
    {
        $file_info = $this->getBaseInfo();
        $file_path = array(
            $this->file_type,
            date('Y/m/d'),
            $this->save_name . ".{$file_info['extension']}"
        );
        $this->file_url = implode('/', $file_path);
        $this->url = $this->file_host . '/' . $this->file_url;
        $this->save_path = $this->file_root . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $file_path);
        $dir = dirname($this->save_path);
        if (!is_dir($dir)) {
            if (!mkdir($dir, 0755, true)) {
                $this->error('保存文件的目录不存在');
            }
        }
    }


    /**
     * 获取要上传文件的基础信息
     * @return array
     */
    protected function getBaseInfo()
    {
        if (!$this->upload_file_base_info) {
            if (isset($_FILES[$this->upload_file_name])) {
                $base_info = $_FILES[$this->upload_file_name];
                if ($base_info['error'] !== 0) {
                    $this->error($this->status_error[$base_info['error']]);
                } else {
                    $extend_info = $this->getFileInfo($base_info);
                    if (!empty($extend_info)) {
                        $base_info = array_merge($base_info, $extend_info);
                    }
                }
                $this->upload_file_base_info = $base_info;
            }
        }

        return $this->upload_file_base_info;
    }


    /**
     * 获取文件详细信息
     *
     * @param $tmp
     *
     * @return mixed
     */
    protected function getFileInfo($tmp)
    {
        $file_info = pathinfo($tmp['name']);
        $file['extension'] = $file_info['extension'];
        $file['filename'] = $file_info['basename'];
        if (!in_array($file['extension'], $this->file_ext[$this->file_type])) {
            $this->error('不支持上传此格式的文件.');
        }
        $file['size'] = (int)filesize($tmp['tmp_name']);
        if ($file['size'] > $this->file_size) {
            $this->error('文件大小超出上传限制大小：' . $this->file_size / 1048576 . 'MB');
        }
        return $file;
    }

    /**
     * 获取图片详细信息
     *
     * @param $images
     *
     * @return array
     */
    protected function getImageInfo($images)
    {
        $image_info = getimagesize($images);
        if (false !== $image_info) {
            $image_ext = strtolower(image_type_to_extension($image_info[2]));
            $image_type = substr($image_ext, 1);
            $image_size = filesize($images);

            $info = array(
                'width' => $image_info[0],
                'height' => $image_info[1],
                'ext' => $image_ext,
                'file_type' => $image_type,
                'size' => $image_size,
                'mime' => $image_info['mime'],
            );
            $this->upload_file_base_info += $info;
            return $info;
        } else {
            return array();
        }
    }


    protected function error($msg)
    {
        $arr = array('error' => 1, 'message' => $msg);
        echo json_encode($arr);
        exit;
    }

    private function randName($prefix = '')
    {
        return $prefix . time() . mt_rand(100000, 999999);
    }

}